const utils = require("./util.js");
const CRC = require("./crc8.js");

const app = getApp();
let isandroid = "android"; //默认当前手机是安卓

wx.getSystemInfo({
  success(res) {
    // 获取当前手机系统类型
    isandroid = res.platform;
  }
});

function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

let ble = {
  /**
   * 流程：
   * 1.先初始化蓝牙适配器，
   * 2.获取本机蓝牙适配器的状态，
   * 3.开始搜索，当停止搜索以后在开始搜索，就会触发蓝牙是配置状态变化的事件，
   * 4.搜索完成以后获取所有已经发现的蓝牙设备，就可以将devices中的设备Array取出来，
   * 5.然后就可以得到所有已经连接的设备了
   */
  startScan() {
    let that = this;
    that._discoveryStarted = false;
    app.setGlobalData({
      useStatus: 2,
      isBinding: false,
      connected: false,
      name: '',
      timeout: true
    })
    that.openBluetoothAdapter();
  },

  //初始化小程序蓝牙模块
  openBluetoothAdapter() {
    let that = this;
    wx.openBluetoothAdapter({
      success(res) {
        console.log("打开蓝牙适配器成功！\n");
        // app.globalData.isopen = true
        app.setGlobalData({
          isopen: true
        })
        that.getBluetoothAdapterState();
      },
      fail(err) {
        isopen: true;
        app.showModal1("蓝牙开关未开启");
        console.log("蓝牙开关未开启 \n");
      }
    });

    //监听蓝牙适配器状态变化事件
    wx.onBluetoothAdapterStateChange(function (res) {
      console.log("onBluetoothAdapterStateChange", res);
      let isDvailable = res.available; //蓝牙适配器是否可用
      if (isDvailable) {
        that.getBluetoothAdapterState();
      } else {
        that.stopBluetoothDevicesDiscovery(); //停止搜索
        that.setData({
          devices: []
        });
        app.showModal1("蓝牙开关未开启");
      }
    });
  },

  //关闭蓝牙模块，使其进入未初始化状态。
  closeBluetoothAdapter() {
    wx.closeBluetoothAdapter();
    this._discoveryStarted = false;
  },

  //获取本机蓝牙适配器状态
  getBluetoothAdapterState() {
    let that = this;
    wx.getBluetoothAdapterState({
      success(res) {
        console.log(res);
        let isDiscov = res.discovering; //是否正在搜索设备
        let isDvailable = res.available; //蓝牙适配器是否可用
        if (isDvailable) {
          console.log("本机蓝牙适配器状态：可用 \n");
          if (!isDiscov) {
            that.startBluetoothDevicesDiscovery();
          } else {
            console.log("已在搜索设备 \n");
          }
        }
      }
    });
  },

  //开始扫描附近的蓝牙外围设备。
  //注意，该操作比较耗费系统资源，请在搜索并连接到设备后调用 stop 方法停止搜索。
  startBluetoothDevicesDiscovery() {
    let that = this;
    if (that._discoveryStarted) {
      return;
    }
    that._discoveryStarted = true;
    app.showLoading("搜索连接等待中");
    setTimeout(function () {
      wx.hideLoading(); //隐藏loading
    }, 10000);
    wx.startBluetoothDevicesDiscovery({
      services: [],
      allowDuplicatesKey: true, //是否允许重复上报同一设备, 如果允许重复上报，则onDeviceFound 方法会多次上报同一设备，但是 RSSI(信号) 值会有不同
      success(res) {
        that.onBluetoothDeviceFound(); //监听寻找到新设备的事件
      }
    });
  },

  //停止搜寻附近的蓝牙外围设备。若已经找到需要的蓝牙设备并不需要继续搜索时，建议调用该接口停止蓝牙搜索。
  stopBluetoothDevicesDiscovery() {
    console.log("停止搜寻附近的蓝牙外围设备 \n");
    wx.stopBluetoothDevicesDiscovery();
  },

  //监听寻找到新设备的事件
  onBluetoothDeviceFound() {
    let that = this;
    let plateItem = app.globalData.plateList[app.globalData.plateIdx]
    wx.onBluetoothDeviceFound(function (res) {
      res.devices.forEach(function (device) {
        if (!device.name && !device.localName) {
          return;
        }
        const foundDevices = app.globalData.devices;
        const idx = inArray(foundDevices, "deviceId", device.deviceId);
        const data = {};
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device;
        } else {
          data[`devices[${idx}]`] = device;
        }
        console.log('device', device)
        if (plateItem && plateItem.devId && device.deviceId == plateItem.devId) {
          that.createBLEConnection(device.deviceId, device.localName)
        } else if (device.name === app.globalData.bleName || device.localName === app.globalData.bleName) {
          that.createBLEConnection(device.deviceId, device.localName)
        }
      });
    });
    // 10秒未进行连接，则停止搜索
    setTimeout(function () {
      that.stopBluetoothDevicesDiscovery(); //停止搜索
      if (!app.globalData.connected) {
        app.setGlobalData({
          useStatus: 2,
          isBinding: false,
          connected: false,
          name: ''
        })
      }
    }, 10000)
  },

  //连接低功耗蓝牙设备。
  createBLEConnection(devId, name) {
    let that = this;
    console.log("正在连接，请稍后..\n");
    wx.createBLEConnection({
      deviceId: devId,
      success(res) {
        console.log("配对成功,获取服务..\n", res);
        let plateList = app.globalData.plateList
        plateList[app.globalData.plateIdx].devId = devId
        app.globalData.plateList = plateList
        let alias1 = utils.getPalteAlias(name.substring(0, name.length - 7))
        let alias2 = utils.getPalteAlias(name.substring(0, name.length - 6))
        app.setGlobalData({
          connected: true,
          name: alias1 ? alias1 + name.substring(name.length - 7) : alias2 + name.substring(name.length - 6),
          devId: devId,
          isBinding: plateList[app.globalData.plateIdx].lockId ? true : false
        })

        that.getBLEDeviceServices(devId);
      },

      fail(err) {
        wx.hideLoading(); //隐藏loading
        console.log(err)
        console.log("连接失败，错误码：" + err.errCode + "\n");
        if (err.errCode === -1) {
          app.setGlobalData({
            connected: true,
            isBinding: app.globalData.plateList[app.globalData.plateIdx].lockId ? true : false
          })
        } else {
          if (err.errCode === 10012) {
            wx.showModal({
              title: "提示",
              content: "连接超时,请重试!",
              showCancel: false,
              success: function (res) {
                if (res.confirm) {
                  that.startScan();
                }
              }
            });
          } else if (err.errCode === 10013) {
            wx.showModal({
              title: "提示",
              content: "连接失败,蓝牙地址无效!",
              showCancel: false,
              success: function (res) {
                if (res.confirm) {
                  that.startScan();
                }
              }
            });
          } else {
            wx.showModal({
              title: "提示",
              content: "连接失败,请重试!",
              showCancel: false,
              success: function (res) {
                if (res.confirm) {
                  that.startScan();
                }
              }
            });
            // + err.errCode10003原因多种：蓝牙设备未开启或异常导致无法连接;蓝牙设备被占用或者上次蓝牙连接未断开导致无法连接
          }
          that.closeBLEConnection();
        }
      }
    });
    that.stopBluetoothDevicesDiscovery(); //停止搜索
  },

  //断开与低功耗蓝牙设备的连接
  closeBLEConnection() {
    wx.closeBLEConnection({
      deviceId: this.data.devId
    });
    app.setGlobalData({
      connected: false,
      isBinding: false
    })
  },

  //获取蓝牙设备所有 service（服务）
  getBLEDeviceServices(devId) {
    let that = this;
    wx.getBLEDeviceServices({
      deviceId: devId,
      success(res) {
        console.log('service（服务）', res)
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            // 该服务是否为主服务
            // let s = res.services[i].uuid;
            app.setGlobalData({
              deviceId: devId,
              serviceId: res.services[i].uuid
            })
            // app.globalData.deviceId = devId
            // app.globalData.serviceId = res.services[i].uuid

            //获取特征值
            that.getBLEDeviceCharacteristics();
            // 如果是isPrimary, 就不需要继续执行
            break
          }
        }
      }
    });
  },

  //返回蓝牙是否正处于链接状态
  onBLEConnectionStateChange(onFailCallback) {
    wx.onBLEConnectionStateChange(function (res) {
      // 该方法回调中可以用于处理连接意外断开等异常情况
      console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`);
      return res.connected;
    });
  },

  //断开与低功耗蓝牙设备的连接
  closeBLEConnection() {
    let that = this;
    wx.closeBLEConnection({
      deviceId: app.globalData.deviceId
    })
    app.globalData.connected = false
    wx.showToast({
      title: '连接已断开',
      icon: 'success'
    });
  },

  //获取蓝牙设备某个服务中的所有 characteristic（特征值）
  getBLEDeviceCharacteristics(order) {
    let that = this;
    wx.getBLEDeviceCharacteristics({
      deviceId: app.globalData.deviceId,
      serviceId: app.globalData.serviceId,
      success(res) {
        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i]
          if (item.uuid.includes('FFE1')) { //该特征值是否支持 notify或indicate 操作
            console.log("该特征值支持 notify 操作:" + item.uuid + "\n");
            app.globalData.notifyCharacteristicId = item.uuid
            app.globalData.writeCharacteristicId = item.uuid
            let lockId = app.globalData.plateList[app.globalData.plateIdx].lockId

            console.log('lockId 二次判断', lockId)
            // 蓝牙连接上之后要延迟0.5秒在验证密码
            setTimeout(function() {
              that.etBind()
            }, 500)

            // 验证密码没有返回 重新发
            setTimeout(function() {
              if (app.globalData.timeout) {
                that.etBind()
              }
            }, 5000)
            that.notifyBLECharacteristicValueChange();
          }
          if (item.uuid.includes('FFE2')) {
            app.globalData.ffe2CharacteristicId = item.uuid
            // that.ffe2BLECharacteristicValueChange();
            that.notifyBLECharacteristicValueChange(app.globalData.ffe2CharacteristicId)
          }
        }
      },
    })
  },

  //启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值。
  //注意：必须设备的特征值支持notify或者indicate才可以成功调用，具体参照 characteristic 的 properties 属性
  notifyBLECharacteristicValueChange(characteristicId = app.globalData.notifyCharacteristicId) {
    let that = this;
    wx.notifyBLECharacteristicValueChange({
      state: true, // 启用 notify 功能
      deviceId: app.globalData.deviceId,
      serviceId: app.globalData.serviceId,
      characteristicId: characteristicId,
      success(res) {
        // wx.hideLoading();
        console.log('notifyBLECharacteristicValueChange', res)
        console.log("notify启动成功" + res.errMsg + "\n");
        that.onBLECharacteristicValueChange(); //监听特征值变化
      },
      fail(res) {
        console.log('notify启动失败', res)
        wx.showToast({
          title: 'notify启动失败',
          mask: true
        });
        setTimeout(function () {
          wx.hideToast();
        }, 2000)
      }
    })
  },

  //监听低功耗蓝牙设备的特征值变化。必须先启用notify接口才能接收到设备推送的notification。
  onBLECharacteristicValueChange() {
    let that = this;
    wx.onBLECharacteristicValueChange(function (res) {
      console.log('onBLECharacteristicValueChange', res)
      let resValue = utils.ab2hext(res.value); // 16进制字符串
      console.log(resValue)
      that.parseRes(resValue)
    });
  },

  //向低功耗蓝牙设备特征值中写入二进制数据。
  //注意：必须设备的特征值支持write才可以成功调用，具体参照 characteristic 的 properties 属性
  writeBLECharacteristicValue(order, characteristicId = app.globalData.writeCharacteristicId) {
    let that = this;
    let byteLength = order.byteLength;
    console.log("当前执行指令的字节长度:" + byteLength + "\n");
    console.log(app.globalData.deviceId)
    console.log(app.globalData.serviceId)

    wx.writeBLECharacteristicValue({
      deviceId: app.globalData.deviceId,
      serviceId: app.globalData.serviceId,
      characteristicId: characteristicId,
      // 这里的value是ArrayBuffer类型
      value: order.slice(0, 20),
      success(res) {
        if (byteLength > 20) {
          setTimeout(function () {
            that.writeBLECharacteristicValue(order.slice(20, byteLength));
          }, 150);
        }
        console.log("写入成功：" + res.errMsg + "\n");
      },

      fail(res) {
        console.log("写入失败" + res.errMsg + "\n");

        // wx.showModal({
        //   title: "提示",
        //   content: "操作失败!",
        //   showCancel: false
        // });
      }
    })
  },

  parseRes(resData) {
    let that = this
    if (!resData) return false
    let typeCode = resData.substring(4, 6)
    let resCode = resData.substring(6, 8)

    console.log('反馈', resData, typeof (resData))
    switch (resData) {
      case '0100':
        app.showModal('同步车牌成功')
        break
    }
    switch (typeCode) {
      case '0A':
        // 密码验证反馈
        console.log('密码验证反馈', resData, resCode)
        app.globalData.timeout = false
        wx.hideLoading()
        if (resCode === '01') {
          app.setGlobalData({
            useStatus: 1
          })

          // if (!app.globalData.plateList[app.globalData.plateIdx].lockId) {
          //   app.setGlobalData({
          //     binding: true
          //   })
          // }
        } else if (resCode === '02') {
          app.setGlobalData({
            useStatus: 2

          })
          app.showModal('密码验证错误')
        } else if (resCode === '03') {
          app.setGlobalData({
            useStatus: 3
          })
          app.showModal('设备已锁定, 请等待6分钟')
        }
        break
      case '0C':
        // 密码修改反馈
        if (resCode === '01') {
          app.showModal('密码修改成功')
        } else if (resCode === '02') {
          app.showModal('密码修改失败')
        } else {
          app.showModal('修改密码失败')
        }
        break
      case '07':
        if (app.globalData.canBind) {
          // 绑定反馈
          let lockId = resData.substring(6, 30)
          let plateList = app.globalData.plateList
          plateList[app.globalData.plateIdx].lockId = lockId
          app.globalData.plateList = plateList
          // 用于首页监听
          app.setGlobalData({
            lockId: lockId
          })
          // that.handleTemperature()
          wx.hideToast()
        }
        break
      case '08':
        // 温度数据反馈
        let tempsymbol = resData.substring(30, 32)
        let tempInt = resData.substring(32, 34)
        let tempdecimal = resData.substring(34, 36)
        let temperature = (tempsymbol === '02' ? '-' : '') + parseInt(tempInt, 16) + '.' + parseInt(tempdecimal, 16)
        console.log(temperature)
        // app.globalData.temperature = temperature
        app.setGlobalData({
          temperature: temperature
        })
        break
    }
  },

  // 密码验证
  etBind() {
    let password = utils.decimal2Hex(app.globalData.plateList[app.globalData.plateIdx].password)
    let crc8 = CRC(`FA0D09${password}`)
    let orderStr = `FA0D09${password}${crc8}16`
    let order = utils.HexString2Bytes(orderStr)
    console.log(orderStr)
    ble.writeBLECharacteristicValue(order)
  },

  // 温度
  handleTemperature() {
    let lockId = app.globalData.plateList[app.globalData.plateIdx].lockId
    let crc8 = CRC(`FA1106${lockId}`)
    let orderStr = `FA1106${lockId}${crc8}16`
    let order = utils.HexString2Bytes(orderStr)
    ble.writeBLECharacteristicValue(order)
  },
}

module.exports = ble